package com.abluedog.state;

import com.abluedog.RandomSurvival;
import com.abluedog.player.PlayerData;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.ServerScoreboard;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.PersistentState;
import net.minecraft.world.PersistentStateManager;
import net.minecraft.world.World;

import java.util.*;

public class BreakBlocksCountLoaderAndSaver extends PersistentState {

    public HashMap<UUID, PlayerData> players = new HashMap<>();

    private static final Type<BreakBlocksCountLoaderAndSaver> type = new Type<>(
            BreakBlocksCountLoaderAndSaver::new,
            BreakBlocksCountLoaderAndSaver::createFromNbt,
            null
    );

    private static BreakBlocksCountLoaderAndSaver createFromNbt(NbtCompound tag, RegistryWrapper.WrapperLookup wrapperLookup) {
        BreakBlocksCountLoaderAndSaver state = new BreakBlocksCountLoaderAndSaver();
        NbtCompound playersNbt = tag.getCompound("players");
        playersNbt.getKeys().forEach(key -> {
            PlayerData playerData = new PlayerData();
            playerData.setBreakBlocksCount(playersNbt.getCompound(key).getInt("breakBlocksCount"));
            playerData.setTotalBreakBlocksCount(playersNbt.getCompound(key).getInt("totalBreakBlocksCount"));
            playerData.setGuaranteedWinning(playersNbt.getCompound(key).getBoolean("guaranteedWinning"));
            NbtCompound prizeDrawRecord = playersNbt.getCompound(key).getCompound("prizeDrawRecord");
            int[] prizeDrawRecordMapKeys = playersNbt.getIntArray("prizeDrawRecordMapKey");
            HashMap<Integer, Integer> integerIntegerHashMap = new HashMap<>();
            for (int prizeDrawRecordMapKey : prizeDrawRecordMapKeys) {
                int anInt = prizeDrawRecord.getInt(String.valueOf(prizeDrawRecordMapKey));
                integerIntegerHashMap.put(prizeDrawRecordMapKey, anInt);
            }
            playerData.setPrizeDrawRecord(integerIntegerHashMap);
            UUID uuid = UUID.fromString(key);
            state.players.put(uuid, playerData);
        });

        return state;
    }

    @Override
    public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
        NbtCompound playersNbt = new NbtCompound();
        players.forEach((uuid, playerData) -> {
            NbtCompound playerDataNbt = new NbtCompound();
            playerDataNbt.putInt("breakBlocksCount", playerData.getBreakBlocksCount());
            playerDataNbt.putInt("totalBreakBlocksCount", playerData.getTotalBreakBlocksCount());
            playerDataNbt.putInt("secondaryRewardCounter", playerData.getSecondaryRewardCounter());
            playerDataNbt.putBoolean("guaranteedWinning", playerData.getGuaranteedWinning());
            NbtCompound prizeDrawRecord = new NbtCompound();
            playerData.getPrizeDrawRecord().forEach((key, value) -> {
                prizeDrawRecord.putInt(key.toString(), value);
            });
            playerDataNbt.put("prizeDrawRecord", prizeDrawRecord);
            playerDataNbt.putIntArray("prizeDrawRecordMapKey",new ArrayList<>(playerData.getPrizeDrawRecord().keySet()));
            playersNbt.put(uuid.toString(), playerDataNbt);
        });
        nbt.put("players", playersNbt);
        return nbt;
    }

    public static BreakBlocksCountLoaderAndSaver getServerState(MinecraftServer server) {
        PersistentStateManager persistentStateManager = Objects.requireNonNull(server.getWorld(World.OVERWORLD)).getPersistentStateManager();

        BreakBlocksCountLoaderAndSaver state = persistentStateManager.getOrCreate(type, RandomSurvival.MOD_ID);

        state.markDirty();

        return state;
    }

    public static PlayerData getPlayDate(PlayerEntity player) {
        BreakBlocksCountLoaderAndSaver serverState = getServerState(Objects.requireNonNull(player.getWorld().getServer()));

        return serverState.players.computeIfAbsent(player.getUuid(), uuid -> new PlayerData());
    }
}
